﻿#pragma once

#include "TextConfig.hpp"
#include "DynamicArray.hpp"
#include "Unicode.hpp"
#include "Tstring.hpp"
#include <fstream>

namespace helpers {

	namespace text {
#if 0
		/**
		* 文本编码器;
		*/
		class Codec
		{
		public:
			/**
			* 构造函数;
			*/
			Codec(void)
				: _internalEncoding(CODEC_INTERNAL_ENCODING)
				, _inputEncoding(UNKNOWN)
				, _outputEncoding(UNKNOWN)
				, _stringStream()
			{

			}

			/**
			* 构造函数(复制);
			*/
			Codec(const Codec& o)
				: _internalEncoding(CODEC_INTERNAL_ENCODING)
				, _inputEncoding(o.getInputEncoding())
				, _outputEncoding(o.getOutputEncoding())
				, _stringStream()
			{
				_stringStream.str("");
				_stringStream << o.getStringStream().str();
			}

			/**
			* 析构函数;
			*/
			virtual ~Codec(void)
			{
				//TODO: 添加资源清理代码;
			}
			
		public:
			void reset()
			{
				ByteArray().swap(_bytes);
			}

		public:

			// 操作符重载;

			/**
			* 赋值复制操作;
			* @param [in] o 文本编码器对象;
			* @return 返回进行赋值复制后的对象;
			*/
			Codec& operator = (const Codec& o)
			{
				_inputEncoding = o._inputEncoding;
				_outputEncoding = o._outputEncoding;
				_stringStream.str("");
				_stringStream << o.getStringStream().str();
				return *this;
			}

			/**
			 * 输入多字节字符串;
			 * @param [in] s 字符串指针;
			 * @return 返回对象本身;
			 */
			Codec& operator << (const char* s)
			{
				if (!s)
					return *this;

				if (*s == '\0') {
					reset();
					return *this;
				}

				if (_internalEncoding == UTF16) {
					const ByteArray& ba = Unicode::toUtf16(s, _inputEncoding);
					const wchar_t* tmp = ba.data();
					append(tmp, wcslen(tmp));
				} else if (_internalEncoding == _inputEncoding) {
					append(s, strlen(s));
				} else {
					const ByteArray& b1 = Unicode::toUtf16(s, _inputEncoding);
					const ByteArray& b2 = Unicode::fromUtf16(static_cast<const char*>(b1), _internalEncoding);
					char* tmp = b2.data();
					append(tmp, strlen(tmp));
				}
				
				return *this;
			}
			
			void append(const void* buf, size_t size)
			{
				_bytes.resize(_length + size);
				memcpy(_bytes.data() + _length, buf, size);
				_length += size;
			}

			char str()
			{

			}

			/**
			* 输入多字节字符串;
			* @param [in] s 字符串指针;
			* @return 返回对象本身;
			*/
			Codec& operator << (const std::string& s)
			{
				operator<<(s.c_str());
			}

			/**
			 * 输入宽字节(UTF16)字符串;
			 * @param [in] s 字符串指针;
			 * @return 返回对象本身;
			 */
			Codec& operator << (const wchar_t* s)
			{
				if (!s)
					return *this;
				if (*s == L'\0') {
					reset();
					return *this;
				}
				if (_internalEncoding != UTF16) {
					const ByteArray& ba = Unicode::fromUtf16(s, _internalEncoding);
					char* tmp = ba.data();
					append(tmp, strlen(tmp));
				} else {
					append(s, wcslen(s));
				}
				return *this;
			}

			/**
			* 输入多字节字符串;
			* @param [in] s 字符串指针;
			* @return 返回对象本身;
			*/
			Codec& operator << (const std::wstring& s)
			{
				operator<<(s.c_str());
			}

			/**
			* 设定输入字符串编码;
			* @param [in] e 输入字符串编码;
			* @return 返回对象本身;
			*/
			Codec& operator << (const CodePage e)
			{
				_inputEncoding = e;
				return *this;
			}

			
			/// 将编码器内字符串输出到另一个编码器;
			/// @param [in] o 文本编码器;
			/// @return 返回对象本身;
			Codec& operator << (const Codec& o)
			{
				_stringStream << o.getStringStream().str();
				return *this;
			}

			Codec& operator << (std::ifstream& ifs)
			{
				ifs.seekg(0, std::ios::end);
				size_t l = ifs.tellg();
				ByteArray b1(l+1);
				char *p = static_cast<char *>(b1);
				ifs.seekg(0, std::ios::beg);
				if (ifs.good()) {
					ifs.read(p, l);
					p[l] = '\0';
					_stringStream << p;
				}
				return *this;
			}

			
			/// 设定输出字符串编码;
			/// @param [in] e 输出字符串编码;
			/// @return 返回对象本身;
			Codec& operator >> (const CodePage e)
			{
				_outputEncoding = e;
				return *this;
			}

			
			/// 输出编码器内数据到多字节字符串对象;
			/// @pre 确保输出编码不是宽字节(UTF16)编码
			/// @param [in,out] s 接收编码后数据的多字节字符串对象;
			/// @return 无返回值;
			void operator >> (std::string& s) const
			{
				if (_length == 0) {
					return ;
				}
				
				if (_internalEncoding == _outputEncoding) {
					s += _bytes.data();
				} else if (_internalEncoding == UTF16) {
					const ByteArray& b1 = Unicode::fromUtf16( , _outputEncoding);
				}
				
				
				{
					if (_internalEncoding == UTF16) {
						const wchar_t *p = reinterpret_cast<const wchar_t *>(str.c_str());
						const ByteArray& b1 = Unicode::fromUtf16(p , _outputEncoding);
						s += static_cast<const char *>(b1);
					} else {
						const ByteArray& b1 = Unicode::toUtf16(str, _internalEncoding);
						const ByteArray& b2 = Unicode::fromUtf16(static_cast<const wchar_t *>(b1), _outputEncoding);
						s += static_cast<const char *>(b2);
					}
				}
			}
			
			/// 输出编码器内数据到宽字节字符串对象;
			/// @param [in,out] s 接收编码后数据的宽字节字符串对象;
			/// @note 只能输出UTF16编码字符串
			/// @return 无返回值;
			void operator >> (std::wstring& s) const
			{
				const std::string& str = _stringStream.str();
				if (str.empty())
					return;
				if (_internalEncoding == UTF16) {
					s += reinterpret_cast<const wchar_t *>(str.c_str());
				} else {
					const ByteArray& b1 = Unicode::toUtf16(str, _internalEncoding);
					s += static_cast<const wchar_t *>(b1);
				}
			}

			/// 输出编码器内数据到多字节流对象;
			/// @param [in,out] os 接收编码后数据的多字节流对象;
			/// @return 无返回值;
			void operator >> (std::ostream& os) const
			{
				const std::string& str = _stringStream.str();
				if (str.empty())
					return;
				/* 如果内部编码格式与输出编码格式一致,
				* 则不需要转换即可直接输出; */
				if (_internalEncoding == _outputEncoding) {
					os << reinterpret_cast<const char *>(str.c_str());
				} else {
					/* 如果内部编码为 UNICODE,
					* 则可跳过转为 UNICODE 的步骤直接可转成目标编码; */
					if (_internalEncoding == UTF16) {
						const wchar_t *wcs = reinterpret_cast<const wchar_t *>(str.c_str());
						const ByteArray& b1 = Unicode::fromUtf16(wcs , _outputEncoding);
						os << static_cast<const char *>(b1);
					} else {
						const ByteArray& b1 = Unicode::toUtf16(str, _internalEncoding);
						const ByteArray& b2 = Unicode::fromUtf16(static_cast<const wchar_t *>(b1), _outputEncoding);
						os << static_cast<const char *>(b2);
					}
				}
			}

			void operator >> (ByteArray& ba) const
			{
				const std::string& str = _stringStream.str();
				if (str.empty()) {
					return ;
				}
				if (_internalEncoding == _outputEncoding) {
					ba.resize(str.length());
					memcpy(ba.data(), str.c_str(), str.length());
				} else if (_internalEncoding == UTF16) {
					Unicode::fromUtf16(reinterpret_cast<const wchar_t *>(str.c_str()), _outputEncoding).swap(ba);
				} else if (_outputEncoding == UTF16) {
					Unicode::toUtf16(str, _internalEncoding).swap(ba);
				} else {
					Unicode::toUtf16(str, _internalEncoding).swap(ba);
					Unicode::fromUtf16(reinterpret_cast<const wchar_t *>(ba.data()), _outputEncoding).swap(ba);
				}
			}

			/**
			* 输出编码器内数据到宽字节流对象;
			* @param [in,out] os 接收编码后数据的宽字节流对象;
			* @return 无返回值;
			*/
			void operator >> (std::wostream& os) const
			{
				const std::string& str = _stringStream.str();
				if (str.empty())
					return;
				/* 如果内部编码格式为 UNICODE,
				* 则不需要转换即可直接输出; */
				if (_internalEncoding == UTF16) {
					os << reinterpret_cast<const wchar_t *>(str.c_str());
				} else {
					ByteArray b1 = Unicode::toUtf16(str, _internalEncoding);
					os << static_cast<wchar_t *>(b1);
				}
			}

			/**
			* 输出编码器内数据到多字节流对象(友元操作);
			* @param [in,out] os 接收编码后数据的多字节流对象;
			* @param [in] tc 文本编码器对象;
			* @return 多字节流对象本身;
			*/
			friend std::ostream& operator << (std::ostream& os, const Codec& tc)
			{
				tc >> os;
				return os;
			}

			/**
			* 输出编码器内数据到宽字节流对象(友元操作);
			* @param [in,out] os 接收编码后数据的宽字节流对象;
			* @param [in] tc 文本编码器对象;
			* @return 宽字节流对象本身;
			*/
			friend std::wostream& operator << (std::wostream& os, const Codec& tc)
			{
				tc >> os;
				return os;
			}

			friend std::ifstream& operator >> (std::ifstream& ifs, Codec& tc)
			{
				tc << ifs;
				return ifs;
			}

			// 属性操作;

			/**
			* 获取输入字符传编码;
			* @return 返回输入字符传编码;
			*/
			const CodePage getInputEncoding() const
			{
				return _inputEncoding;
			}

			/**
			* 获取输出字符传编码;
			* @return 返回输出字符传编码;
			*/
			const CodePage getOutputEncoding() const
			{
				return _outputEncoding;
			}

			/**
			* 获取字符串流对象;
			* @return 返回字符串流对象;
			*/
			const std::stringstream& getStringStream() const
			{
				return _stringStream;
			}

		protected:
			CodePage		_internalEncoding; /**< 内部字符串编码 */
			CodePage		_inputEncoding; /**< 输入字符串编码 */
			CodePage		_outputEncoding; /**< 输出字符串编码 */
			std::stringstream	_stringStream; /**< 字符串流对象 */
			ByteArray _bytes;
			size_t _length;


		}; // class Codec;


		class Codec2 
		{
		
		};

#endif
	} // namespace Text;

} // namespace helpers


